
import datetime
import os.path
import re
from dataclasses import asdict
from typing import Optional, List

from csr_utils import log,get_root_dir
from dao import project_dao
from orm_domain.project import Project


class ProjectService:

    def save(self, name, sign, git_id=None, version=None) -> bool:

        # 项目名称不能为空
        if not name:
            log.warning("项目名称不能为空！")
            return False

        # 项目标识不能为空
        if not sign:
            log.warning("项目标识不能为空！")
            return False

        # 项目标识命名要符合规则：只支持字母、数字、下划线。
        valid_pattern = r"^[0-9a-zA-Z_]{1,}$"
        result = re.match(valid_pattern, sign)
        if not result:
            log.warning("项目标识只支持英文、数字和下划线！")
            return False

        # 项目标识不能重复
        result = project_dao.get(sign=sign)
        if result:
            # todo: fix软删除影响
            log.warning("项目标识已经存在，不允许重复！")
            return False

        # 生成项目目录
        self.allocate_workspace(sign)

        # 实例化项目对象
        project = Project()
        project.name = name
        project.sign = sign
        project.git_id = git_id
        project.version = version
        project.is_del = 0

        # 存入数据库
        flag = project_dao.save(project)
        log.info(f"新增项目结果：{flag}")
        return flag

    def get_list(self) -> List[Project]:
        # 查询所有记录
        result = project_dao.get_list(is_del=0)
        log.info(f"查询项目结果：{result}")
        return result

    def get_by_id(self, _id):
        # 按编号查询记录
        result = project_dao.get(id=_id, is_del=0)
        log.info(f"查询项目结果：{result}")
        return result

    def get_by_name(self, name) -> Optional[Project]:
        # 按项目名称查询记录
        result = project_dao.get(name=name, is_del=0)
        log.info(f"查询项目结果：{result}")
        return result

    def get_by_sign(self, sign) -> Optional[Project]:
        # 按项目标识查询记录
        result = project_dao.get(sign=sign, is_del=0)
        log.info(f"查询项目结果：{result}")
        return result

    # todo: 遗留问题⭐️ -统一通过注解判空
    # todo: 参数改为实力类
    def update(self, _id: int, name: str, sign: str, git_id: int, version: str) -> bool:
        """
        更新
        备注：第一个版本暂不支持修改项目标识
        """

        # 项目id不能为空
        if not _id:
            log.warning("项目id不能为空！")
            return False

        # 名字标识不能为空
        if not name:
            log.warning("项目名称不能为空！")
            return False

        # 项目标识不能为空
        if not sign:
            log.warning("项目标识不能为空！")
            return False

        # 项目标识命名要符合规则：只支持字母、数字、下划线。
        # todo: 封装公共方法。
        # todo: 更新标识不能重复
        # todo: 判断条件包括 id
        valid_pattern = r"^[0-9a-zA-Z_]{1,}$"
        result = re.match(valid_pattern, sign)
        if not result:
            log.warning("项目标识只支持英文、数字和下划线！")
            return False

        # 要更新的数据应当存在且有效
        result = project_dao.get(id=_id)
        if not result:
            log.warning("要更新的数据不存在或无效！")
            return False

        # 实例化目标对象
        result.name = name
        result.git_id = git_id
        result.version = version
        result.sign = sign

        # 执行更新
        flag = project_dao.update()
        log.info(f"更新项目结果：{flag}")
        return flag

    def delete(self, _id) -> bool:

        # 项目编号不能为空
        if not _id:
            log.warning("项目编号不能为空！")
            return False

        # 数据应当存在且有效
        result = project_dao.get(id=_id)
        if not result:
            log.warning("要删除的数据不存在或无效！")
            return False

        # 翻转状态
        result.is_del = 1

        # 执行删除
        flag = project_dao.delele()
        log.info(f"删除项目结果：{flag}")
        return flag

    def allocate_workspace(self, sign: str) -> str:
        """
        生成子目录
        :param sign: 项目标识
        """

        # TODO：遗留问题：⭐️ 这里的空间路径需要确认，硬编码还是读取数据库配置项， 是否添加全局配置表
        # Todo：把workspace 替换为常量类 -> 小佛， 按业务模型建立常量类
        workspace_path = os.sep.join([get_root_dir(), "cus_workspace", sign])

        # 如果目录不存在，则创建目录
        is_exist = os.path.exists(workspace_path)
        if not is_exist:
            log.debug(f"创建项目目录：{workspace_path}")
            os.makedirs(workspace_path)

        return workspace_path